<?php

namespace app\business;
use app\business\BaseBusiness;
use app\libs\Functions;
use app\libs\Predis;
use think\Config;

class RedisCache extends BaseBusiness
{

    const KEY_USER_INFO = "cq:hashTable:userInfo:userNo:";
    const KEY_USER_ASSET = "cq:hashTable:userAsset:userNo:";   //inex:hashTable:userAsset:userNo:234324:coinId:1
    const KEY_PAIR = "cq:hashTable:pair:pairId:";
    const KEY_MARKET = "cq:hashTable:market:api_key:";
    const LOCK_TIME_OUT = 3;

    public $redis = null;
    /********************用户登录缓存----start------***********************/
    public function __construct()
    {
        $this->redis = new Predis();
    }
    public function userCache($userNo, $tokenPassword, $user)
    {
        $key = self::KEY_USER_INFO . $userNo.':tokenPassword:'.$tokenPassword;
        $timeout = Config::get('lifetime.login');

        $addRedis=$this->redis->hMset($key,$user);
        $this->redis->expire($key,$timeout);
//        $pipe = $this->redis->multi(\Redis::PIPELINE);
//        $addRedis = $pipe->hMset($key, $user)->setTimeout($key, $timeout)->exec();
        return $addRedis;
    }


    //incid
    public function checkToken($token,$tokenPassword)
    {
        $user = $this->decryptToken($token);
        if($user['login_status'] != 1){
            $this->result['status'] = -2;
            $this->result['msg'] = '需要登录1';
            return $this->result;
        }
        if (!isset($user) || !isset($user['user_no'])) {
            $this->result['status'] = -2;
            $this->result['msg'] = '需要登录2';
            return $this->result;
        }
        $key = self::KEY_USER_INFO . $user['user_no'].':tokenPassword:'.$tokenPassword;
        //判断incidtoken是否过期
        $filed = ['refresh_token_expire_in','expire_in','refresh_token','token'];
        $userToken = $this->redis->hMGet($key,$filed);
        if ($userToken['token'] === false) {
            $this->result['status'] = -2;
            $this->result['msg'] = '需要登录3';
            return $this->result;
        }

        //判断token是否被劫持
        if($userToken['token'] != $token){
            $this->result['status'] = -2;
            $this->result['msg'] = '需要登录4';
            return $this->result;
        }

        $timeout = Config::get('lifetime.login');
        $this->redis->hMset($key,$key, ['api_refresh_time' => time()]);
        $this->redis->expire($key,$timeout);
       // $pipe->setTimeout($key, $timeout)->hMset($key, ['api_refresh_time' => time()])->exec();

        $this->result['status'] = 1;
        $this->result['data'] = $user;
        return $this->result;
    }

    //获取token
    public function getToken($token)
    {
        $userNo = $this->decryptToken($token);
        if (!$userNo) {
            return false;
        }
        $key = self::KEY_USER_INFO . $userNo;
        $token = $this->redis->get($key);
        if (!$token) {
            return false;
        }
        return true;
    }


    public function tradeLock($token,$tokenPassword)
    {
        $user = $this->decryptToken($token);

        if($user['login_status'] != 1){
            $this->result['status'] = -2;
            $this->result['msg'] = 'login_expire';
            return $this->result;
        }

        if (!isset($user) || !isset($user['user_no'])) {
            $this->result['status'] = -2;
            $this->result['msg'] = 'login_expire';
            return $this->result;
        }
        $key = self::KEY_USER_INFO . $user['user_no'].':tokenPassword:'.$tokenPassword;
        $userToken = $this->redisUser->hMGet($key, ['api_refresh_time','tradeLock','inex_token']);

        if ($userToken['inex_token'] === false) {
            $this->result['status'] = -2;
            $this->result['msg'] = 'login_expire';
            return $this->result;
        }

        if ((time() - $userToken['api_refresh_time']) > $this->config['lifetime']['deal']) {
            //设置交易锁
            $this->redisUser->hMset($key,['tradeLock' => 1]);

            $this->result['status'] = -3;
            return $this->result;
        }

        //判断是否存在交易锁
        if(isset($userToken['tradeLock']) && $userToken['tradeLock'] == 1){
            $this->result['status'] = -3;
            return $this->result;
        }


//        return true;
        $pipe = $this->redisUser->multi(\Redis::PIPELINE);
        $timeout = $this->config['lifetime']['deal'];
        $pipe->setTimeout($key, $timeout)->hMset($key, ['api_refresh_time' => time()])->exec();

        $this->result['status'] = 1;
        $this->result['data'] = $user;
        return $this->result;
    }



    /***************************用户登录缓存---end----******************************/
    //获取hash表中的部分信息    getUserInfo
    public function getUserInfo($userNo, $tokenPassword = '', $fieldData)
    {
        $key = self::KEY_USER_INFO . $userNo . ':tokenPassword:' . $tokenPassword;
        return $this->redis->hMGet($key, $fieldData);
    }

    //设置hash表中的某字段
    public function setUserInfo($userNo, $tokenPassword = '', $fieldData)
    {
        $key = self::KEY_USER_INFO . $userNo . ':tokenPassword:' . $tokenPassword;
        return $this->redisUser->hMset($key, $fieldData);

    }

    //删除hash表中的用户信息    getUserInfo
    public function delUserInfo($userNo , $tokenPassword = '')
    {
        $key = self::KEY_USER_INFO . $userNo . ':tokenPassword:' . $tokenPassword;
        return $this->redisUser->del($key);
    }

    //生成token
    function createToken($data,$tokenPassword)
    {
        $data['tokenPassword'] = $tokenPassword;
        $str = json_encode($data);
        return Functions::encrypt($str, Config::get('salt'));
    }

    //解析token
    function decryptToken($token)
    {
        try {
            $tokenJson = Functions::decrypt($token, Config::get('salt'));
        } catch (\Exception $e) {
            $msg  = "File：" . $e->getFile() . "\n";
            $msg .= "Line：" . $e->getLine() . "\n";
            $msg .= "Message：" . $e->getMessage() . "\n";

            return false;
        }
        $userToken = json_decode($tokenJson, true);
        //login_status = -2  尚未通过手机或谷歌验证
//        if (isset($userToken['login_status'])) {
//            if ($userToken['login_status'] == 2) {
//                return false;
//            }
//        }

        return $userToken;
    }

    //incid
    public function refreshToken($refresh_token = '')
    {
        $url = $this->config['user_center']['url'].'token';
        $data['appid'] = $this->config['user_center']['appid'];
        $data['secret'] = $this->config['user_center']['secret'];
        $data['grant_type'] = 'refresh_token';
        $data['code'] = 'CODE';
        $data['scope'] = 'snsapi_base';
        $data['refresh_token'] = $refresh_token;
        $data['mode'] = 'authorization_code';

        $refreshToken = $this->functions->http_request($url,'POST',$data);
        return $refreshToken;
    }


    //创建订单加锁限制次数
    public function tradeAddLock($api_key){
        $key = "inex:setting:transfer:tradeAdd:api_key:" . $api_key;
        $value = $this->redisUser->get($key);
        if ($value) {
            return false;
        }
        $lock = $this->redisUser->setnx($key, 1);
        if ($lock) {
            $this->redisUser->expire($key, self::LOCK_TIME_OUT);
            return true;
        }
    }
    // 创建订单解锁
    public function unlockTradeAdd($api_key){
        $key = "inex:setting:transfer:tradeAdd:api_key:" . $api_key;
        $this->redisUser->del($key);
    }

    //订单加锁限制次数
    public function tradeListLock($api_key){
        $key = "inex:setting:transfer:tradeList:api_key:" . $api_key;
        $value = $this->redisUser->get($key);
        if ($value) {
            return false;
        }

        $lock = $this->redisUser->setnx($key, 1);
        if ($lock) {
            $this->redisUser->expire($key, self::LOCK_TIME_OUT);
            return true;
        }
    }
    // 订单解锁
    public function unlockTradeList($api_key){
        $key = "inex:setting:transfer:tradeList:api_key:" . $api_key;
        $this->redisUser->del($key);
    }

    //订单详情加锁限制次数
    public function orderDetailsLock($api_key){
        $key = "inex:setting:transfer:orderDetails:api_key:" . $api_key;
        $value = $this->redisUser->get($key);
        if ($value) {
            return false;
        }

        $lock = $this->redisUser->setnx($key, 1);
        if ($lock) {
            $this->redisUser->expire($key, self::LOCK_TIME_OUT);
            return true;
        }
    }
    // 订单详情解锁
    public function unlockOrderDetails($api_key){
        $key = "inex:setting:transfer:orderDetails:api_key:" . $api_key;
        $this->redisUser->del($key);
    }

    //撤单加锁限制次数
    public function orderCancelLock($api_key){
        $key = "inex:setting:transfer:orderCancel:api_key:" . $api_key;
        $value = $this->redisUser->get($key);
        if ($value) {
            return false;
        }

        $lock = $this->redisUser->setnx($key, 1);
        if ($lock) {
            $this->redisUser->expire($key, self::LOCK_TIME_OUT);
            return true;
        }
    }
    // 撤单解锁
    public function unlockOrderCancel($api_key){
        $key = "inex:setting:transfer:orderCancel:api_key:" . $api_key;
        $this->redisUser->del($key);
    }

    //查看资产加锁限制次数
    public function publishLock($api_key){
        $key = "inex:setting:transfer:myAsset:api_key:" . $api_key;
        $value = $this->redisUser->get($key);
        if ($value) {
            return false;
        }

        $lock = $this->redisUser->setnx($key, 1);
        if ($lock) {
            $this->redisUser->expire($key, self::LOCK_TIME_OUT);
            return true;
        }
    }
    //查看资产加锁限制次数
    public function unlockPublish($api_key){
        $key = "inex:setting:transfer:myAsset:api_key:" . $api_key;
        $this->redisUser->del($key);
    }

    //获取牌价加锁限制次数
    public function quotationLock($pairId){
        $key = "inex:setting:transfer:quotation:paiId:" . $pairId;
        $value = $this->redisUser->get($key);
        if ($value) {
            return false;
        }

        $lock = $this->redisUser->setnx($key, 1);
        if ($lock) {
            $this->redisUser->expire($key, self::LOCK_TIME_OUT);
            return true;
        }
    }
    // 获取牌价解锁
    public function unlockQuotation($pairId){
        $key = "inex:setting:transfer:quotation:paiId:" . $pairId;
        $this->redisUser->del($key);
    }

    //获取深度加锁限制次数
    public function depthLock($pairId){
        $key = "inex:setting:transfer:depth:paiId:" . $pairId;
        $value = $this->redisUser->get($key);
        if ($value) {
            return false;
        }

        $lock = $this->redisUser->setnx($key, 1);
        if ($lock) {
            $this->redisUser->expire($key, self::LOCK_TIME_OUT);
            return true;
        }
    }
    // 获取深度解锁
    public function unlockDepth($pairId){
        $key = "inex:setting:transfer:depth:paiId:" . $pairId;
        $this->redisUser->del($key);
    }

    //获取成交单加锁限制次数
    public function clinchLock($pairId){
        $key = "inex:setting:transfer:clinch:paiId:" . $pairId;
        $value = $this->redisUser->get($key);
        if ($value) {
            return false;
        }

        $lock = $this->redisUser->setnx($key, 1);
        if ($lock) {
            $this->redisUser->expire($key, self::LOCK_TIME_OUT);
            return true;
        }
    }
    // 获取成交单解锁
    public function unlockClinch($pairId){
        $key = "inex:setting:transfer:clinch:paiId:" . $pairId;
        $this->redisUser->del($key);
    }

    //获取成交单加锁限制次数
    public function klineLock($pairId){
        $key = "inex:setting:transfer:kline:paiId:" . $pairId;
        $value = $this->redisUser->get($key);
        if ($value) {
            return false;
        }

        $lock = $this->redisUser->setnx($key, 1);
        if ($lock) {
            $this->redisUser->expire($key, self::LOCK_TIME_OUT);
            return true;
        }
    }
    // 获取成交单解锁
    public function unlockKline($pairId){
        $key = "inex:setting:transfer:kline:paiId:" . $pairId;
        $this->redisUser->del($key);
    }

    public function getAssets($userNo){
        $coins = $this->redisUser->zRevRange('inex:zset:coin',0,-1);
        $pipe = $this->redisUser->multi(\Redis::PIPELINE);
        foreach ($coins as $v){
            $key = "inex:hashTable:userAsset:userNo:" . $userNo . ":coinId:" . $v;
            $pipe->hgetAll($key);
        }
        $result = $pipe->exec();
        return $result;
    }

    /***************************做市商api---end**************************************/
    public function getAsset($ykey,$hkey,$fields = array(),$begin = 0,$over = -1){
        $pairs = $this->redisUser->zRevRange($ykey,$begin,$over);
        $pipe = $this->redisUser->multi(\Redis::PIPELINE);
        foreach ($pairs as $v){
            $pipe->hMget($hkey . $v,$fields);
        }
        $result = $pipe->exec();
        return $result;

    }

    //订单锁，锁创建订单、提现操作
    public function lockDepositAddress($userNo){
        $orderLockKey = "inex:string:depositAddress:lock:userNo:" . $userNo;
        $lock = $this->redisUser->setnx($orderLockKey,1);
        if($lock){
            $this->redisUser->expire($orderLockKey,10);
            return true;
        }
        return false;
    }

    public function unlockDepositAddress($userNo){
        $orderLockKey = "inex:string:depositAddress:lock:userNo:" . $userNo;
        $this->redisUser->del($orderLockKey);
    }

    public function getCoins(){
        $key = 'inex:zset:coin';
        return $this->redisUser->zrange($key,0,-1);
    }

    //锁仓加锁
    public function redislockAmountOrder($userNo,$coinId){
        $key = "inex:string:lockAmountOrder:$userNo:$coinId";
        if($this->redisUser->set($key,1,array('nx','ex' => 5))){
            return true;
        }else{
            return false;
        }
    }

    //获取锁仓锁
    public function getRedislockAmountOrder($userNo,$coinId){
        $key = "inex:string:lockAmountOrder:$userNo:$coinId";
        if($this->redisUser->get($key)){
            return true;
        }else{
            return false;
        }
    }

    //提现加锁
    public function redislockWithdrawOrder($userNo,$coinId){
        $key = "inex:string:lockWithdrawOrder:$userNo:$coinId";
        if($this->redisUser->set($key,1,array('nx','ex' => 5))){
            return true;
        }else{
            return false;
        }
    }

    //获取锁仓锁;

    public function getRedislockWithdrawOrder($userNo,$coinId){
        $key = "inex:string:lockWithdrawOrder:$userNo:$coinId";
        if($this->redisUser->get($key)){
            return true;
        }else{
            return false;
        }
    }

}